package com.snail.workflow.api.common;

import com.snail.common.core.constant.SecurityConstants;
import com.snail.common.core.domain.R;
import com.snail.common.core.exception.ServiceException;
import com.snail.common.core.utils.SpringUtils;
import com.snail.workflow.api.RemoteWorkflowService;
import com.snail.workflow.api.constant.WorkflowConstants;
import com.snail.workflow.api.domain.dto.*;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 流程基础接口
 * @Author: Snail
 * @CreateDate: 2022/8/3 14:24
 * @Version: V1.0
 */
public interface WorkflowBasicService {

    /**
     * 获取feign接口
     *
     * @return 结果
     */
    default RemoteWorkflowService getService() {
        return SpringUtils.getBean(RemoteWorkflowService.class);
    }

    /**
     * 初始化流程任务
     *
     * @param dto 业务数据
     * @return 结果
     */
    default WorkflowDto initWorkflow(TaskInitWorkflowDto dto) {
        //设置流程定义key
        dto.setProcDefKey(getBizWorkflowKey());
        //设置流程名称
        dto.setBizName(getBizWorkflowName(dto.getBizId()));
        //设置流程变量
        Map<String, Object> variables = setWorkflowVariables(dto.getBizId());
        dto.setVariables(variables);
        //初始化流程
        R<WorkflowDto> r = getService().initWorkflow(dto, SecurityConstants.INNER);
        if (r.isOk()) {
            return r.getData();
        } else {
            throw new ServiceException(r.getMsg());
        }
    }

    /**
     * 获取下一审批节点
     *
     * @param taskInitNextDto 初始化下一节点
     * @return 结果
     */
    default TaskParamDto initNextNode(TaskInitNextDto taskInitNextDto) {
        //提交前校验业务数据
        checkBusinessData(taskInitNextDto.getBizId());
        //初始化流程
        R<TaskParamDto> r = getService().initNextNode(taskInitNextDto, SecurityConstants.INNER);
        if (r.isOk()) {
            TaskParamDto paramDto = r.getData();
            //设置默认审批人
            setDefaultApproveUser(paramDto);
            return paramDto;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }


    /**
     * 审批流程任务
     *
     * @param taskSubmitDto 提交参数
     * @return 结果
     */
    default Boolean submitTask(@RequestBody TaskSubmitDto taskSubmitDto) {
        //流程审批前
        beforeSubmitTask(taskSubmitDto.getBizId(), WorkflowConstants.TASK_TYPE_SUBMIT);
        //提交流程
        R<WorkflowDto> r = getService().submitTask(taskSubmitDto, SecurityConstants.INNER);
        if (r.isOk()) {
            afterSubmitTask(r.getData(), WorkflowConstants.TASK_TYPE_SUBMIT);
            return Boolean.TRUE;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }

    /**
     * 驳回流程任务
     *
     * @param taskSubmitDto 提交参数
     * @return 结果
     */
    default Boolean rejectTask(@RequestBody TaskSubmitDto taskSubmitDto) {
        beforeSubmitTask(taskSubmitDto.getBizId(), WorkflowConstants.TASK_TYPE_REJECT);
        R<WorkflowDto> r = getService().rejectTask(taskSubmitDto, SecurityConstants.INNER);
        if (r.isOk()) {
            afterSubmitTask(r.getData(), WorkflowConstants.TASK_TYPE_REJECT);
            return Boolean.TRUE;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }

    /**
     * 取消流程任务
     *
     * @param taskSubmitDto 提交参数
     * @return 结果
     */
    default Boolean cancelTask(@RequestBody TaskSubmitDto taskSubmitDto) {
        beforeSubmitTask(taskSubmitDto.getBizId(), WorkflowConstants.TASK_TYPE_CANCEL);
        R<WorkflowDto> r = getService().cancelTask(taskSubmitDto, SecurityConstants.INNER);
        if (r.isOk()) {
            afterSubmitTask(r.getData(), WorkflowConstants.TASK_TYPE_CANCEL);
            return Boolean.TRUE;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }

    /**
     * 委派流程任务
     *
     * @param taskSubmitDto 提交参数
     * @return 结果
     */
    default Boolean delegateTask(TaskSubmitDto taskSubmitDto) {
        beforeSubmitTask(taskSubmitDto.getBizId(), WorkflowConstants.TASK_TYPE_DELEGATE);
        R<WorkflowDto> r = getService().delegateTask(taskSubmitDto, SecurityConstants.INNER);
        if (r.isOk()) {
            afterSubmitTask(r.getData(), WorkflowConstants.TASK_TYPE_DELEGATE);
            return Boolean.TRUE;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }


    /**
     * 转办任务
     *
     * @param taskSubmitDto 提交参数
     * @return 结果
     */
    default Boolean turnToDoTask(TaskSubmitDto taskSubmitDto) {
        beforeSubmitTask(taskSubmitDto.getBizId(), WorkflowConstants.TASK_TYPE_TURN_TO_DO);
        R<WorkflowDto> r = getService().turnToDoTask(taskSubmitDto, SecurityConstants.INNER);
        if (r.isOk()) {
            afterSubmitTask(r.getData(), WorkflowConstants.TASK_TYPE_TURN_TO_DO);
            return Boolean.TRUE;
        } else {
            throw new ServiceException(r.getMsg());
        }
    }


    /**
     * 撤回任务任务
     *
     * @param taskWithdrawDto 提交参数
     * @return 结果
     */
    default Boolean withdrawTask(TaskWithdrawDto taskWithdrawDto) {
        beforeSubmitTask(taskWithdrawDto.getBizId(), WorkflowConstants.TASK_TYPE_TURN_TO_DO);
        R<Boolean> r = getService().withdrawTask(taskWithdrawDto, SecurityConstants.INNER);
        if (r.isOk()) {
            return r.getData();
        } else {
            throw new ServiceException(r.getMsg());
        }
    }


    /**
     * 获取流程定义key
     *
     * @return 结果
     */
    String getBizWorkflowKey();

    /**
     * 获取流程名称
     *
     * @param bizId 业务id
     * @return 结果
     */
    String getBizWorkflowName(String bizId);

    /**
     * 任务处理前
     *
     * @param bizId         业务id
     * @param operationType 操作类型 #{@link WorkflowConstants}
     */
    default void beforeSubmitTask(String bizId, String operationType) {

    }

    /**
     * 任务处理后
     *
     * @param workflowDto 业务流程数据
     * @param submitType  操作类型 #{@link WorkflowConstants}
     */
    default void afterSubmitTask(WorkflowDto workflowDto, String submitType) {

    }

    /**
     * 设置流程变量
     *
     * @param bizId 业务id
     * @return 结果
     */
    default Map<String, Object> setWorkflowVariables(String bizId) {
        return new HashMap<>(64);
    }

    /**
     * 设置默认审批人
     *
     * @param data 流程参数
     * @return 结果
     */
    default TaskParamDto setDefaultApproveUser(TaskParamDto data) {
        return data;
    }

    /**
     * 校验业务数据
     *
     * @param bizId 业务id
     */
    default void checkBusinessData(String bizId) {

    }

}
